/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package NodeManager;

import Rdf.RdfWriter;
import com.hp.hpl.jena.rdf.model.Bag;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.NodeIterator;
import com.hp.hpl.jena.rdf.model.ResIterator;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.Statement;
import java.io.File;
import java.util.Vector;

/**
 *
 * @author Sean
 */
public class NodeManager {

    private Node _node1;
    private Node _node2;
    private Node _node3;
    private Model _rdfModel;

    public NodeManager(Node node1, Node node2, Node node3) throws IllegalArgumentException {
        _rdfModel = ModelFactory.createDefaultModel();

        if (node1.NodeName.compareToIgnoreCase(node2.NodeName) == 0 ||
                node1.NodeName.compareToIgnoreCase(node3.NodeName) == 0 ||
                node2.NodeName.compareToIgnoreCase(node3.NodeName) == 0) {
            throw new IllegalArgumentException("All nodes must have unique names.");
        }

        _node1 = node1;
        _node2 = node2;
        _node3 = node3;
    }

    public NodeManager(File rdfModelFile) {
        // TODO where a model file already exists.
    }

    public Model GetRdfModel() {
        return _rdfModel;
    }

    public void AddFile(File file) throws Exception {

        Node firstNode = null;
        Node secondNode = null;

        // find the best 2 nodes to add the file into.
        if (_node1.GetFileCount() <= _node2.GetFileCount() && _node1.GetFileCount() <= _node3.GetFileCount()) {
            // Node 1 has the lowest amount of files, therefore use Node1 as the First Node
            firstNode = _node1;
            if (_node2.GetFileCount() <= _node3.GetFileCount()) {
                //Node2 has the second lowest amount of files, therefore use Node2 as the second node
                secondNode = _node2;
            } else {
                secondNode = _node3;
            }

        } else if (_node2.GetFileCount() <= _node1.GetFileCount() && _node2.GetFileCount() <= _node3.GetFileCount()) {
            firstNode = _node2;
            if (_node1.GetFileCount() <= _node3.GetFileCount()) {
                secondNode = _node1;
            } else {
                secondNode = _node3;
            }

        } else if (_node3.GetFileCount() <= _node1.GetFileCount() && _node3.GetFileCount() <= _node2.GetFileCount()) {
            firstNode = _node3;
            if (_node1.GetFileCount() <= _node2.GetFileCount()) {
                secondNode = _node1;
            } else {
                secondNode = _node2;
            }
        }

        firstNode.AddFile(file);
        secondNode.AddFile(file);
        RdfWriter.AddFile(_rdfModel, file, firstNode, secondNode);
    }

    public Node GetNodeByName(String nodeName) {

        if (nodeName.compareToIgnoreCase(_node1.NodeName) == 0) {
            return _node1;
        } else if (nodeName.compareToIgnoreCase(_node2.NodeName) == 0) {
            return _node2;
        } else if (nodeName.compareToIgnoreCase(_node3.NodeName) == 0) {
            return _node3;
        } else {
            return null;
        }
    }

    public NodeFile GetNodeFile(String fileName) {

        String myFileURI = Global.Data.BaseURI + fileName;

        // Get the resource from the model that matches the current filenmae
        Resource file = _rdfModel.getResource(myFileURI);

        // Get the Nodes property
        Statement nodes = file.getProperty(RdfWriter.CreateProperty("Nodes"));

        // Get the bag that is associated with the Nodes property
        Bag bag = nodes.getBag();

        NodeIterator iter = bag.iterator();
        NodeFile nodeFile = new NodeFile();
        
        // Get the nodes that are associated with this NodeFile.
        nodeFile.FirstNode = GetNodeByName(iter.next().toString());
        nodeFile.SecondNode = GetNodeByName(iter.next().toString());
        nodeFile.FileName = fileName;

        return nodeFile;

    }

    public Vector<NodeFile> GetAllNodeFiles() {

        Vector<NodeFile> allFiles = new Vector<NodeFile>();

        // TODO this function could probably be optimised a bit more.

        // Get all resources in the model with a property of "Filename"
        ResIterator iter = _rdfModel.listSubjectsWithProperty(RdfWriter.CreateProperty("Filename"));

        while (iter.hasNext()) {
            // Iterate through each resource
            Resource r = iter.nextResource();
            // Get the actual filename property
            Statement fileName = r.getProperty(RdfWriter.CreateProperty("Filename"));
            // Get each each NodeFile that matches the Filename
            allFiles.add(GetNodeFile(fileName.getObject().toString()));
        }

        return allFiles;
    }
}
